package com.zlb.configuration;

import com.zlb.filter.AnyRolesAuthorizationFilter;
import com.zlb.filter.JwtAuthFilter;
import java.util.Arrays;
import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {

  @Bean
  public FilterRegistrationBean<Filter> filterRegistrationBean(SecurityManager securityManager)
      throws Exception {
    FilterRegistrationBean<Filter> filterRegistration = new FilterRegistrationBean<Filter>();
    filterRegistration.setFilter((Filter) shiroFilter(securityManager).getObject());
    filterRegistration.addInitParameter("targetFilterLifecycle", "true");
    filterRegistration.setAsyncSupported(true);
    filterRegistration.setEnabled(true);
    filterRegistration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
    return filterRegistration;
  }


  @Bean
  public Authenticator authenticator() {
    ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
    authenticator.setRealms(Arrays.asList(jwtShiroRealm(), dbShiroRealm()));
    authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
    return authenticator;
  }

  @Bean
  protected SessionStorageEvaluator sessionStorageEvaluator() {
    DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
    sessionStorageEvaluator.setSessionStorageEnabled(false);
    return sessionStorageEvaluator;
  }

  @Bean("dbRealm")
  public Realm dbShiroRealm() {
    DbShiroRealm myShiroRealm = new DbShiroRealm();
    myShiroRealm.setCredentialsMatcher(new DbCredentialsMatcher());
    return myShiroRealm;
  }

  @Bean("jwtRealm")
  public Realm jwtShiroRealm() {
    JWTShiroRealm myShiroRealm = new JWTShiroRealm();
    myShiroRealm.setCredentialsMatcher(new JWTCredentialsMatcher());
    return myShiroRealm;
  }

  /**
   * 设置过滤器
   */
  @Bean("shiroFilter")
  public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
    factoryBean.setSecurityManager(securityManager);
    //登录多的url.
    factoryBean.setLoginUrl("/login");
    //登录成功访问url
    factoryBean.setSuccessUrl("/index");
    //无权限访问失败URL
    factoryBean.setUnauthorizedUrl("/unauthorized");
    //设置filter chain
    Map<String, Filter> filterMap = factoryBean.getFilters();
    filterMap.put("authcToken", createAuthFilter());
    filterMap.put("anyRole", createRolesFilter());
    factoryBean.setFilters(filterMap);
    factoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition().getFilterChainMap());

    return factoryBean;
  }

  /**
   * 密码比较器
   */
//  @Bean
//  public CredentialsMatcher credentialsMatcher() {
////    return new HashedCredentialsMatcher("MD5");
//    return new JWTCredentialsMatcher();
//  }
  @Bean
  protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
    chainDefinition.addPathDefinition("/image/**", "anon");
    chainDefinition.addPathDefinition("/login", "noSessionCreation,anon");
    chainDefinition.addPathDefinition("/logout", "noSessionCreation,authcToken[permissive]");
    chainDefinition.addPathDefinition("/admin/**",
        "noSessionCreation,authcToken,anyRole[admin,manager]"); //只允许admin或manager角色的用户访问
    chainDefinition.addPathDefinition("/article/list", "noSessionCreation,authcToken");
    chainDefinition.addPathDefinition("/article/*", "noSessionCreation,authcToken[permissive]");
    chainDefinition.addPathDefinition("/**", "noSessionCreation,authcToken");
    return chainDefinition;
  }

  protected JwtAuthFilter createAuthFilter() {
    JwtAuthFilter jwtAuthFilter = new JwtAuthFilter();
    jwtAuthFilter.setLoginUrl("/login");
    return jwtAuthFilter;
  }

  protected AnyRolesAuthorizationFilter createRolesFilter() {
    return new AnyRolesAuthorizationFilter();
  }

}
